package cn.ivicar.mapper.ibatis.model;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.log4j.Logger;

import com.google.inject.Inject;

public class BaseExample {
    private final static Logger logger = Logger.getLogger(BaseExample.class);

    private ResultMap resultMap;

    /**
     * This field was generated by MyBatis Generator. This field corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected String orderByClause;

    /**
     * This field was generated by MyBatis Generator. This field corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected int limitStart = -1;

    /**
     * This field was generated by MyBatis Generator. This field corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected int limitCount;

    /**
     * This field was generated by MyBatis Generator. This field corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected boolean distinct;

    /**
     * This field was generated by MyBatis Generator. This field corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected List<Criteria> oredCriteria;

    protected boolean appendOrderByClause = false;

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public BaseExample(ResultMap resultMap) {
        this.oredCriteria = new ArrayList<Criteria>();
        this.resultMap = resultMap;
    }

    public BaseExample() {
        this.oredCriteria = new ArrayList<Criteria>();
    }

    public ResultMap getResultMap() {
        return this.resultMap;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public void setOrderByClause(String orderByClause) {
        if (!isAppendOrderByClause()) {
            StringBuffer buffer = new StringBuffer("");
            String[] orders = StringUtils.split(orderByClause, ",");
            for (String ord : orders) {
                String msg = "----DB SQL ---- order ";
                String[] fieldord = ord.trim().split(" ");
                String fieldName = null;
                String sortby = null;
                if (fieldord.length > 0) {
                    fieldName = getColumnFromProperty(fieldord[0].trim());
                    if (fieldName == null) {
                        fieldName = fieldord[0].trim();
                    }
                    buffer.append(fieldName);
                }
                if (fieldord.length > 1) {
                    sortby = fieldord[1];
                    buffer.append(" " + sortby);
                }
                if (fieldord.length > 2) {
                    msg = msg + orderByClause;
                    throw new RuntimeException(msg);
                }
                buffer.append(",");
            }
            if (!buffer.toString().equals("")) {
                orderByClause = buffer.substring(0, buffer.length() - 1);
            }
        }

        this.orderByClause = orderByClause;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public String getOrderByClause() {
        return this.orderByClause;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public void setLimitStart(int limitStart) {
        this.limitStart = limitStart;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public int getLimitStart() {
        return this.limitStart;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public void setLimitCount(int limitCount) {
        this.limitCount = limitCount;
        if (this.limitCount != -1 && this.limitStart == -1) {
            this.limitStart = 0;
        }
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public int getLimitCount() {
        return this.limitCount;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public void setDistinct(boolean distinct) {
        this.distinct = distinct;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public boolean isDistinct() {
        return this.distinct;
    }

    public void setAppendOrderByClause(boolean appendOrderByClause) {
        this.appendOrderByClause = appendOrderByClause;
    }

    public boolean isAppendOrderByClause() {
        return this.appendOrderByClause;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public List<Criteria> getOredCriteria() {
        return this.oredCriteria;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public void or(Criteria criteria) {
        this.oredCriteria.add(criteria);
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public Criteria or() {
        Criteria criteria = createCriteriaInternal();
        this.oredCriteria.add(criteria);
        return criteria;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public Criteria createCriteria() {
        Criteria criteria = createCriteriaInternal();
        if (this.oredCriteria.size() == 0) {
            this.oredCriteria.add(criteria);
        }
        return criteria;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected Criteria createCriteriaInternal() {
        Criteria criteria = new Criteria(this.resultMap);
        return criteria;
    }

    /**
     * This method was generated by MyBatis Generator. This method corresponds
     * to the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public void clear() {
        this.oredCriteria.clear();
        this.orderByClause = null;
        this.distinct = false;
    }

    /**
     * Return the column name mapped to a property using a resultmap TODO:
     * duplicated, must be moved to share location
     * 
     * @param propertyName
     * @return
     */
    public String getColumnFromProperty(String propertyName) {
        for (ResultMapping resultMap : this.resultMap.getResultMappings()) {
            if (resultMap.getProperty().equals(propertyName)) {
                return resultMap.getColumn();
            }
        }
        return null;
    }

    /**
     * This class was generated by MyBatis Generator. This class corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    protected abstract static class GeneratedCriteria {
        @Inject
        private ResultMap resultMap;

        protected List<Criterion> criteria;

        protected GeneratedCriteria(ResultMap resultMap) {
            super();
            this.criteria = new ArrayList<Criterion>();
            this.resultMap = resultMap;
        }

        public boolean isValid() {
            return this.criteria.size() > 0;
        }

        public List<Criterion> getAllCriteria() {
            return this.criteria;
        }

        public List<Criterion> getCriteria() {
            return this.criteria;
        }

        protected void addCriterion(String condition) {
            if (condition == null) {
                throw new RuntimeException("Value for condition cannot be null");
            }
            this.criteria.add(new Criterion(condition));
        }

        protected void addCriterion(String condition, Object value, String property) {
            if (value == null) {
                throw new RuntimeException("Value for " + property + " cannot be null");
            }
            this.criteria.add(new Criterion(condition, value));
        }

        protected void addCriterion(String condition, Object value1, Object value2, String property) {
            if (value1 == null || value2 == null) {
                throw new RuntimeException("Between values for " + property + " cannot be null");
            }
            this.criteria.add(new Criterion(condition, value1, value2));
        }

        public ResultMapping getResultMappingFromProperty(String propertyName) {
            for (ResultMapping resultMap : this.resultMap.getResultMappings()) {
                if (resultMap.getProperty().equals(propertyName)) {
                    return resultMap;
                }
            }

            return null;
        }

        public String getColumnFromProperty(String propertyName) {
            ResultMapping mapping = getResultMappingFromProperty(propertyName);
            if (mapping != null) {
                return mapping.getColumn();
            }
            return null;
        }

        @SuppressWarnings("unchecked")
        public <B> Criteria andObjectByExample(B example) throws IllegalAccessException,
                InvocationTargetException, NoSuchMethodException {
            for (String propertyName : (Set<String>) BeanUtils.describe(example).keySet()) {
                String propertyValue = BeanUtils.getProperty(example, propertyName);
                ResultMapping resultMapping = getResultMappingFromProperty(propertyName);
                String columnName = (resultMapping == null) ? null : resultMapping.getColumn();
                if (propertyValue != null && !propertyName.equals("class") && columnName != null) {
                    Class<?> type = resultMapping.getJavaType();
                    if (type == Boolean.class) {
                        propertyValue = (propertyValue.equals("true") || propertyValue.equals("1")) ? "1"
                                : "0";
                        addCriterion(columnName + " = ", propertyValue, propertyName);
                    } else {
                        addCriterion(columnName + " = ", propertyValue, propertyName);
                    }
                }
            }
            return (Criteria) this;
        }

        public Criteria andPropertyIsNull(String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " is null");
            }
            return (Criteria) this;
        }

        public Criteria andPropertyIsNotNull(String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " is not null");
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyEqualTo(T value, String propertyName) {
            ResultMapping resultMapping = getResultMappingFromProperty(propertyName);
            if (resultMapping != null) {
                String columnName = resultMapping.getColumn();
                addCriterion(columnName + " = ", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyEqualToIgnoreCase(String value, String propertyName) {
            ResultMapping resultMapping = getResultMappingFromProperty(propertyName);
            if (resultMapping != null) {
                value = value.toLowerCase();
                String columnName = resultMapping.getColumn();
                addCriterion("lower(" + columnName + ") = ", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyNotEqualTo(T value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " <>", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyGreaterThan(T value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " >", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyGreaterThanOrEqualTo(T value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " >=", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyLessThan(T value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " <", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyLessThanOrEqualTo(T value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " <=", value, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andPropertyIn(List<T> values, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " in", values, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andIdNotIn(List<T> values, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " not in", values, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andIdBetween(T value1, T value2, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " between", value1, value2, propertyName);
            }
            return (Criteria) this;
        }

        public <T> Criteria andIdNotBetween(T value1, T value2, String propertyName) {
            addCriterion(this.getColumnFromProperty(propertyName) + " not between", value1, value2,
                    propertyName);
            return (Criteria) this;
        }

        public Criteria andPropertyLike(String value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " like", value, propertyName);
            }
            return (Criteria) this;
        }

        public Criteria andPropertyNotLike(String value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                addCriterion(columnName + " not like", value, propertyName);
            }
            return (Criteria) this;
        }

        public Criteria andPropertyLikeIgnoreCase(String value, String propertyName) {
            String columnName = this.getColumnFromProperty(propertyName);
            if (columnName != null) {
                value = value.toLowerCase();
                addCriterion("lower(" + columnName + ") like ", value, propertyName);
            }
            return (Criteria) this;
        }

    }

    /**
     * This class was generated by MyBatis Generator. This class corresponds to
     * the database table user
     * 
     * @mbggenerated do_not_delete_during_merge Mon Jan 24 12:32:57 CET 2011
     */
    public static class Criteria extends GeneratedCriteria {

        protected Criteria(ResultMap resultMap) {
            super(resultMap);
        }
    }

    /**
     * This class was generated by MyBatis Generator. This class corresponds to
     * the database table user
     * 
     * @mbggenerated Mon Jan 24 12:32:57 CET 2011
     */
    public static class Criterion {
        private String condition;

        private Object value;

        private Object secondValue;

        private boolean noValue;

        private boolean singleValue;

        private boolean betweenValue;

        private boolean listValue;

        private String typeHandler;

        public String getCondition() {
            return this.condition;
        }

        public Object getValue() {
            return this.value;
        }

        public Object getSecondValue() {
            return this.secondValue;
        }

        public boolean isNoValue() {
            return this.noValue;
        }

        public boolean isSingleValue() {
            return this.singleValue;
        }

        public boolean isBetweenValue() {
            return this.betweenValue;
        }

        public boolean isListValue() {
            return this.listValue;
        }

        public String getTypeHandler() {
            return this.typeHandler;
        }

        protected Criterion(String condition) {
            super();
            this.condition = condition;
            this.typeHandler = null;
            this.noValue = true;
        }

        protected Criterion(String condition, Object value, String typeHandler) {
            super();
            this.condition = condition;
            this.value = value;
            this.typeHandler = typeHandler;
            if (value instanceof List<?>) {
                this.listValue = true;
            } else {
                this.singleValue = true;
            }
        }

        protected Criterion(String condition, Object value) {
            this(condition, value, null);
        }

        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
            super();
            this.condition = condition;
            this.value = value;
            this.secondValue = secondValue;
            this.typeHandler = typeHandler;
            this.betweenValue = true;
        }

        protected Criterion(String condition, Object value, Object secondValue) {
            this(condition, value, secondValue, null);
        }
    }
}
